package com.hxd.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Date;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.hxd.common.Result;
import com.hxd.common.utils.ServletUtils;
import com.hxd.common.utils.StringUtils;
import com.hxd.entity.SysOss;
import com.hxd.oss.OSSFactory;
import com.hxd.service.SysOssService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * <p>
    * 附件表 前端控制器
    * </p>
 *
 * @author zhoujw
 * @since 2019-12-19
 * @version v1.0
 */
@Api(tags="附件表")
@RestController
@RequestMapping("/sys-oss")
public class SysOssController {
	
	@Autowired
	private SysOssService service;
	
	@GetMapping("/{id}")
	@ApiOperation(value = "获取文件")
	public void get(@PathVariable("id") String id, HttpServletResponse response, HttpServletRequest request) {
		if (StringUtils.isBlank(id)) {
			throw new RuntimeException("参数id值为空.");
		}
		SysOss oss = service.getById(id);
		if (oss == null) {
			throw new RuntimeException("该文件不存在.");
		}
		try {
			String fileName = oss.getName();
			// 判断文件类型
			response.setContentType(getContentType(fileName));
			if (service.isVedio(fileName.toLowerCase())) {
				this.sendVideo(request, response, new File(oss.getPath()), fileName);
				return;
			}
			if (!service.isImage(fileName.toLowerCase())) {
				response.addHeader("Content-Disposition", "attachment; filename=" + new String(oss.getName().getBytes(), "iso-8859-1"));
			}
			IOUtils.copy(new FileInputStream(oss.getPath()), response.getOutputStream());
			response.flushBuffer();
		} catch (FileNotFoundException e) {
			throw new RuntimeException("该文件路径不存在.");
		} catch (IOException e) {
			throw new RuntimeException("读取文件异常.");
		}
	}
	
	@PostMapping("/upload")
	@ApiOperation(value = "上传文件")
	public Object post(@RequestParam(value = "file", required = false) MultipartFile file) throws Exception {
		if (file == null || file.isEmpty()) {
			throw new RuntimeException("上传文件不能为空");
		}
		// 上传文件
		String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
		String result = OSSFactory.build().uploadSuffix(file.getBytes(), suffix);
		
		String[] arr = StringUtils.splitByWholeSeparator(result, "|");
		String url = arr[0];
		String path = arr[1];
		String md5 = arr[2];

		// 保存文件信息
		SysOss oss = new SysOss();
		oss.setName(file.getOriginalFilename());
		oss.setUrl(url);
		oss.setPath(path);
		oss.setSuffix(FilenameUtils.getExtension(oss.getName()));
		oss.setMd5(md5);

		service.save(oss);
		return Result.success(oss);
	}

	public String getContentType(String returnFileName) {
		String contentType = "application/octet-stream";
		if (returnFileName.lastIndexOf(".") < 0)
			return contentType;
		returnFileName = returnFileName.toLowerCase();
		returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".") + 1);
		if (returnFileName.equals("html") || returnFileName.equals("htm") || returnFileName.equals("shtml")) {
			contentType = "text/html";
		} else if (returnFileName.equals("apk")) {
			contentType = "application/vnd.android.package-archive";
		} else if (returnFileName.equals("sis")) {
			contentType = "application/vnd.symbian.install";
		} else if (returnFileName.equals("sisx")) {
			contentType = "application/vnd.symbian.install";
		} else if (returnFileName.equals("exe")) {
			contentType = "application/x-msdownload";
		} else if (returnFileName.equals("msi")) {
			contentType = "application/x-msdownload";
		} else if (returnFileName.equals("css")) {
			contentType = "text/css";
		} else if (returnFileName.equals("xml")) {
			contentType = "text/xml";
		} else if (returnFileName.equals("gif")) {
			contentType = "image/gif";
		} else if (returnFileName.equals("jpeg") || returnFileName.equals("jpg")) {
			contentType = "image/jpeg";
		} else if (returnFileName.equals("js")) {
			contentType = "application/x-javascript";
		} else if (returnFileName.equals("atom")) {
			contentType = "application/atom+xml";
		} else if (returnFileName.equals("rss")) {
			contentType = "application/rss+xml";
		} else if (returnFileName.equals("mml")) {
			contentType = "text/mathml";
		} else if (returnFileName.equals("txt")) {
			contentType = "text/plain";
		} else if (returnFileName.equals("jad")) {
			contentType = "text/vnd.sun.j2me.app-descriptor";
		} else if (returnFileName.equals("wml")) {
			contentType = "text/vnd.wap.wml";
		} else if (returnFileName.equals("htc")) {
			contentType = "text/x-component";
		} else if (returnFileName.equals("png")) {
			contentType = "image/png";
		} else if (returnFileName.equals("tif") || returnFileName.equals("tiff")) {
			contentType = "image/tiff";
		} else if (returnFileName.equals("wbmp")) {
			contentType = "image/vnd.wap.wbmp";
		} else if (returnFileName.equals("ico")) {
			contentType = "image/x-icon";
		} else if (returnFileName.equals("jng")) {
			contentType = "image/x-jng";
		} else if (returnFileName.equals("bmp")) {
			contentType = "image/x-ms-bmp";
		} else if (returnFileName.equals("svg")) {
			contentType = "image/svg+xml";
		} else if (returnFileName.equals("jar") || returnFileName.equals("var") || returnFileName.equals("ear")) {
			contentType = "application/java-archive";
		} else if (returnFileName.equals("doc")) {
			contentType = "application/msword";
		} else if (returnFileName.equals("pdf")) {
			contentType = "application/pdf";
		} else if (returnFileName.equals("rtf")) {
			contentType = "application/rtf";
		} else if (returnFileName.equals("xls")) {
			contentType = "application/vnd.ms-excel";
		} else if (returnFileName.equals("ppt")) {
			contentType = "application/vnd.ms-powerpoint";
		} else if (returnFileName.equals("7z")) {
			contentType = "application/x-7z-compressed";
		} else if (returnFileName.equals("rar")) {
			contentType = "application/x-rar-compressed";
		} else if (returnFileName.equals("swf")) {
			contentType = "application/x-shockwave-flash";
		} else if (returnFileName.equals("rpm")) {
			contentType = "application/x-redhat-package-manager";
		} else if (returnFileName.equals("der") || returnFileName.equals("pem") || returnFileName.equals("crt")) {
			contentType = "application/x-x509-ca-cert";
		} else if (returnFileName.equals("xhtml")) {
			contentType = "application/xhtml+xml";
		} else if (returnFileName.equals("zip")) {
			contentType = "application/zip";
		} else if (returnFileName.equals("mid") || returnFileName.equals("midi") || returnFileName.equals("kar")) {
			contentType = "audio/midi";
		} else if (returnFileName.equals("mp3")) {
			contentType = "audio/mpeg";
		} else if (returnFileName.equals("ogg")) {
			contentType = "audio/ogg";
		} else if (returnFileName.equals("m4a")) {
			contentType = "audio/x-m4a";
		} else if (returnFileName.equals("ra")) {
			contentType = "audio/x-realaudio";
		} else if (returnFileName.equals("3gpp") || returnFileName.equals("3gp")) {
			contentType = "video/3gpp";
		} else if (returnFileName.equals("mp4")) {
			contentType = "video/mp4";
		} else if (returnFileName.equals("mpeg") || returnFileName.equals("mpg")) {
			contentType = "video/mpeg";
		} else if (returnFileName.equals("mov")) {
			contentType = "video/quicktime";
		} else if (returnFileName.equals("flv")) {
			contentType = "video/x-flv";
		} else if (returnFileName.equals("m4v")) {
			contentType = "video/x-m4v";
		} else if (returnFileName.equals("mng")) {
			contentType = "video/x-mng";
		} else if (returnFileName.equals("asx") || returnFileName.equals("asf")) {
			contentType = "video/x-ms-asf";
		} else if (returnFileName.equals("wmv")) {
			contentType = "video/x-ms-wmv";
		} else if (returnFileName.equals("avi")) {
			contentType = "video/x-msvideo";
		}
		return contentType;
	}
	
	private void sendVideo(HttpServletRequest request, HttpServletResponse response, File file, String fileName) throws FileNotFoundException, IOException {
		RandomAccessFile randomFile = new RandomAccessFile(file, "r");
		long contentLength = randomFile.length();
		String range = request.getHeader("Range");
		int start = 0, end = 0;
		if (range != null && range.startsWith("bytes=")) {
			String[] values = range.split("=")[1].split("-");
			start = Integer.parseInt(values[0]);
			if (values.length > 1) {
				end = Integer.parseInt(values[1]);
			}
		}
		int requestSize = 0;
		if (end != 0 && end > start) {
			requestSize = end - start + 1;
		} else {
			requestSize = Integer.MAX_VALUE;
		}

		byte[] buffer = new byte[2048];

		response.setHeader("Accept-Ranges", "bytes");
		response.setContentType("video/mp4");
		response.setHeader("ETag", fileName);
		response.setHeader("Last-Modified", new Date().toString());
		// 第一次请求只返回content length来让客户端请求多次实际数据
		if (range == null) {
			response.setHeader("Content-length", contentLength + "");
		} else {
			// 以后的多次以断点续传的方式来返回视频数据
			response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);// 206
			long requestStart = 0, requestEnd = 0;
			String[] ranges = range.split("=");
			if (ranges.length > 1) {
				String[] rangeDatas = ranges[1].split("-");
				requestStart = Integer.parseInt(rangeDatas[0]);
				if (rangeDatas.length > 1) {
					requestEnd = Integer.parseInt(rangeDatas[1]);
				}
			}
			long length = 0;
			if (requestEnd > 0) {
				length = requestEnd - requestStart + 1;
				response.setHeader("Content-length", length + "");
				response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);
			} else {
				length = contentLength - requestStart;
				response.setHeader("Content-length", length + "");
				response.setHeader("Content-Range", "bytes " + requestStart + "-" + (contentLength - 1) + "/" + contentLength);
			}
		}
		
		ServletOutputStream out = response.getOutputStream();
		try {
			int needSize = requestSize;
			randomFile.seek(start);
			while (needSize > 0) {
				int len = randomFile.read(buffer);
				if (needSize < buffer.length) {
					out.write(buffer, 0, needSize);
				} else {
					out.write(buffer, 0, len);
					if (len < buffer.length) {
						break;
					}
				}
				needSize -= buffer.length;
			}
		} catch (Exception e) {
			
		} finally {
			randomFile.close();
			out.close();
		}
	}
	
    /**
     * 分片上传文件
     */
//    @PostMapping("/post")
//	@ApiOperation(value = "分片上传文件")
//    public Result uploadFile(MultipartFile file, String guid, Integer chunk, Integer chunks) throws IOException {
//         boolean isMultipart = ServletFileUpload.isMultipartContent(ServletUtils.getRequest());  
//         if (isMultipart) {
//             service.uploadFile(guid, chunk, chunks, file);
//         }
//         return Result.success();
//    }
    
}
